﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using CarHelpDesk.Web.Models;
using CarHelpDesk.Web.Models.Repositories;
using System.Text;
using System.Web;

namespace CarHelpDesk.Web.Controllers
{
    public class QuestionsController : Controller
    {
        private IQuestionsRepository repo { get; set; }
        private ITagRepository repoTags { get; set; }
        private IAnswersRepository repoAnswers { get; set; }
        private IImagesRepository repoImages { get; set; }

        #region QuestionControllerConstructors
        public QuestionsController()
        {
            repo = new CarHelpDesk.Web.Models.Repositories.LinqRepositories.QuestionsRepository();
            repoTags = new CarHelpDesk.Web.Models.Repositories.LinqRepositories.TagRepository();
            repoAnswers = new CarHelpDesk.Web.Models.Repositories.LinqRepositories.AnswersRepository();
            repoImages = new CarHelpDesk.Web.Models.Repositories.LinqRepositories.ImagesRepository();
        }

        public QuestionsController(IQuestionsRepository qRepository)
        {
            repo = qRepository;
            repoTags = new CarHelpDesk.Web.Models.Repositories.LinqRepositories.TagRepository();
            repoAnswers = new CarHelpDesk.Web.Models.Repositories.LinqRepositories.AnswersRepository();
            repoImages = new CarHelpDesk.Web.Models.Repositories.LinqRepositories.ImagesRepository();
        }

        public QuestionsController(IQuestionsRepository qRepository, ITagRepository cTag)
        {
            repo = qRepository;
            repoTags = cTag;
            repoAnswers = new CarHelpDesk.Web.Models.Repositories.LinqRepositories.AnswersRepository();
            repoImages = new CarHelpDesk.Web.Models.Repositories.LinqRepositories.ImagesRepository();
        }

        public QuestionsController(IQuestionsRepository qRepository, ITagRepository cTag, IAnswersRepository aRepository)
        {
            repo = qRepository;
            repoTags = cTag;
            repoAnswers = aRepository;
            repoImages = new CarHelpDesk.Web.Models.Repositories.LinqRepositories.ImagesRepository();
        }
        #endregion

        /// <summary>
        /// Lists all the questions.
        /// </summary>
        /// <returns></returns>
        public ActionResult Index()
        {
            return View(repo.GetQuestions());
        }

        public ActionResult IndexTag(string id)
        {
            int[] ids;
            if (id!=null && repoTags.HasAllTagName(new string[] { id }, out ids))
            {
                List<Tag> tag = new List<Tag>();
                Tag tg = new Tag();
                tg.ID = ids[0];
                tag.Add(tg);
                return View("Index", repo.SearchByTag(tag));
            
            }
                
                return View("Index", new List<Question>());
        }

        /// <summary>
        /// Lists questions that contain specified in the form keywords.
        /// </summary>
        /// <param name="collection">The collection.</param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult Index(FormCollection collection)
        {
            
            if (collection.AllKeys.Contains("SearchKeys"))
            {
                string catNames;
                List<Tag> selectedCategories = GetCheckedTags(collection, out catNames);
                if (selectedCategories.Count > 0)
                {
                    IQueryable<Question> qlist_cat = repo.SearchByTag(selectedCategories);
                    ViewData["IndexTitle"] =
                    string.Format("Резултати от търсенето в категории <span id='SearchTitle'>{0}</span><br /><br />", catNames);
                    return View(qlist_cat.Distinct());
                }

                string value = collection["SearchKeys"].ToString();
                ViewData["IndexTitle"] =
                    string.Format("Резултати от търсенето на <span id='SearchTitle'>{0}</span><br /><br />", value);
                string[] keys = value.Split(" ".ToCharArray(),
                    StringSplitOptions.RemoveEmptyEntries);

                List<Question> qlist = repo.SearchByText(value).ToList();
               
                if (keys.Count() != 1)
                {
                    foreach (string key in keys)
                    {
                        qlist.AddRange(repo.SearchByText(key).ToList());
                    }
                }
                //search the answers if checked
                if (collection.AllKeys.Contains("srchInAswers") && collection["srchInAswers"].ToString() == "on")
                {
                    qlist.AddRange(repo.SearchInAswers(value).ToList());
                    if (keys.Count() != 1)
                    {
                        foreach (string key in keys)
                        {
                            qlist.AddRange(repo.SearchInAswers(value).ToList());
                        }
                    }
                }

                return View(qlist.Distinct());
            }
            return View(new List<Question>());
        }

        private List<Tag> GetCheckedTags(FormCollection collection, out string names)
        {
            IQueryable<Tag> currentTags = repoTags.GetTags();
            List<Tag> selectedTags = new List<Tag>();
            StringBuilder sb_names = new StringBuilder(); 
            foreach (Tag c in currentTags)
            {
                if (collection.AllKeys.Contains(c.Title) && collection[c.Title].ToString() == "on")
                {
                    selectedTags.Add(c);
                    sb_names.Append(c.Title).Append(" ");
                }
            }

            names = sb_names.ToString();

            return selectedTags;
        }

        //
        // GET: /Questions/Details/5
        //[Authorize(Roles="Moderator")]
        public ActionResult Details(int id)
        {            
            Question question = repo.GetByID(id);
            if (Request.IsAuthenticated)
                ViewData["isFavourite"] = repo.IsFavouritedBy(question.ID, this.GetCurrentUserID());
            else
                ViewData["isFavourite"] = false;

            if (question.QuestionAttentionFlags.Any(flagQ => flagQ.UserID == this.GetCurrentUserID()))
                ViewData["isFlagged"] = true;
            else
                ViewData["isFlagged"] = false;

            //images
            IImagesRepository irepo = new CarHelpDesk.Web.Models.Repositories.LinqRepositories.ImagesRepository();
            List<Image> images = irepo.GetQuestionImages(question.ID);

            if (images.Count >= 1)
            {
                GenerateHTMLString(images);
            }
           
            return View("Details",question);
        }

        public string GenerateHTMLString(List<Image> images)
        {
            string result = "<table id=\"imageList\"> ";
            //int cnt = 1;
            StringBuilder sb = new StringBuilder();
            //sb.Append("<table id=\"imageList\"> ");
            foreach (var item in images)
            {
                //if (cnt % 8 == 0)
                //    result += "</tr><tr>";
                //sb.Append("<tr><td>").Append(Response.BinaryWrite

                string temp = "<tr><td> <asp:Image ID='img_"+item.ID+"' runat=\"server\" ImageUrl='Image/Details/" + item.ID +
                                "' AlternateText='"+item.ImageName +"/> </td></tr>";

                result += string.Format(temp);
            }
            result += "</table>";
            ViewData["tableImages"] = result;//sb.ToString();
            return result;
        }

        /// <summary>
        /// Creates form for creating a new question.
        /// </summary>
        /// <returns></returns>
        public ActionResult Create()
        {
            return View();
        } 


        /// <summary>
        /// Creates the specified question.
        /// </summary>
        /// <param name="question">The question.</param>
        /// <returns></returns>
        [Authorize]
        [HttpPost]
        public ActionResult Create(Question question)
        {
            try
            {
                question.AuthorID = this.GetCurrentUserID();

                if (!string.IsNullOrEmpty(question.Tags))
                {

                    int[] TagsIDs;
                    if (repoTags.HasAllTagName(
                       question.Tags.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries), out TagsIDs))
                    {
                        repo.Create(question);

                        repoTags.AddQuestionTags(TagsIDs, question);

                        foreach (string key in Request.Files)
                        {
                            HttpPostedFileBase file = Request.Files[key];
                            if (file.FileName.Length > 0)
                            {
                                Image image = new Image();
                                image.ImageName = file.FileName;
                                image.ImageNameAlt = file.FileName;
                                image.ContentType = file.ContentType;

                                Int32 length = file.ContentLength;

                                byte[] tempImage = new byte[length];

                                file.InputStream.Read(tempImage, 0, length);
                                image.Data = tempImage;

                                IImagesRepository irepo = new CarHelpDesk.Web.Models.Repositories.LinqRepositories.ImagesRepository();
                                irepo.SaveQuestionImage(image, question.ID);
                            }
                        }


                        return RedirectToAction("Index");
                    }
                    else
                    {
                        ModelState.AddModelError("", "Има грешно въведен етикет.");
                    }
                    return View();
                }
                else
                {
                    repo.Create(question);

                    foreach (string key in Request.Files)
                    {
                        HttpPostedFileBase file = Request.Files[key];
                        if (file.FileName.Length > 0)
                        {
                            Image image = new Image();
                            image.ImageName = file.FileName;
                            image.ImageNameAlt = file.FileName;
                            image.ContentType = file.ContentType;

                            Int32 length = file.ContentLength;

                            byte[] tempImage = new byte[length];

                            file.InputStream.Read(tempImage, 0, length);
                            image.Data = tempImage;

                            IImagesRepository irepo = new CarHelpDesk.Web.Models.Repositories.LinqRepositories.ImagesRepository();
                            irepo.SaveQuestionImage(image, question.ID);
                        }
                    }
                }
                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }       

        [Authorize]
        public ActionResult FavouriteQuestions()
        {
            return PartialView("FavouriteQuestions", repo.GetQuestionsFavouritedBy(this.GetCurrentUserID()));
        }

        [Authorize/*(Roles = "Moderator")*/]
        public ActionResult FlaggedQuestions()
        {
            return PartialView("FlaggedQuestions", repo.GetQuestionsMarkedAsFlagged());
        }

        [HttpPost]
        [Authorize]
        public JsonResult QuestionToogleFavourite(int QuestionID)
        {
            MarkAsFavoriteJsonResult result = new MarkAsFavoriteJsonResult();
            try
            {
                FavouriteQuestion favQuestion = new FavouriteQuestion();
                favQuestion.QuestionID = QuestionID;
                favQuestion.UserID = this.GetCurrentUserID();

                result.IsFavourite = repo.QuestionToogleFavourite(favQuestion);

                result.Success = true;                
            }
            catch
            {
                result.Success = false;
                result.Message = "error";            
            }

            return Json(result);
        }

        [HttpPost]
        [Authorize]
        public JsonResult QuestionToogleFlagged(int QuestionID)
        {
            MarkAsFlaggedJsonResult result = new MarkAsFlaggedJsonResult();
            try
            {
                QuestionAttentionFlag flagQuestion = new QuestionAttentionFlag();
                flagQuestion.QuestionID = QuestionID;
                flagQuestion.UserID = this.GetCurrentUserID();

                result.IsFlagged = repo.QuestionToggleFlagged(flagQuestion);
                result.Success = true;                
            }
            catch
            {
                result.Success = false;
                result.Message = "error";                
            }
            return Json(result);
        }

        [HttpPost]
        public ActionResult Edit(int id, string txtContentEdit)
        {
            repo.UpdateQuestionContentById(id, txtContentEdit);
            return Json(new { txtContentEdit = txtContentEdit });
        }

        //
        // GET: /Questions/Delete/5
 
        public ActionResult Delete(int id)
        {
            repo.DeleteQuestionById(id);
            return RedirectToAction("Index");
        }

        public ActionResult MegaModeratorRevert(int id)
        {
            repo.RevertQuestionById(id);
            return RedirectToAction("Index");
        }

        public ActionResult MegaModeratorDelete(int id)
        {
            List<Answer> answers = repoAnswers.getAnswersByQuestionID(id).ToList();

            foreach (Answer answer in answers)
            {
                repoImages.DeleteAllImagesByAnswerID(answer.ID);
                repoAnswers.DeleteAnswerVoteByAnswerID(answer.ID);
            }
            repoAnswers.DeleteAnswersByQuestionID(id);

            repo.ModeratorDeleteQuestionById(id);
            return RedirectToAction("Index");
        }

        #region JsonResultCustomObjects
        class MarkAsFavoriteJsonResult
        {
            public bool Success;
            public bool IsFavourite;
            public string Message;
        }

        class MarkAsFlaggedJsonResult
        {
            public bool Success;
            public bool IsFlagged;
            public string Message;
        }
        #endregion

        public ActionResult AdvancedSearch()
        {
            //retrieve  all categories
            IQueryable<Tag> categories = repoTags.GetTags();
            
            return PartialView("AdvancedSearch", categories);
        }

    } 
}
